#pragma once

#include "gl/glew.h"
#include <vector>
#include <string>
#include "Renderer.h"
#include "Lights.h"
#include "camera.h"
#include "MeshModel.h"
using namespace std;

class Scene {

	vector<MeshModel*> models;
	vector<Camera*> cameras;
	vector<LightSource*> m_lightSources;
	Renderer *m_renderer;
	//the following two fields will determine the projection cube.
	int activeCamera;
	int activeModel;
	int activeLight;
	int m_drawCameras;
	bool m_drawLights;
	bool flagDrawNormals;
public:
	Scene(Renderer *renderer);
	~Scene();
	void NextModel();
	void PreviousModel();
	void loadOBJModel(string fileName,bool centralize, bool shrink, vec3 mp);
	void draw();
	void drawDemo();
	void TranslateActiveModel(const GLfloat & x_dir, const GLfloat  & y_dir, const GLfloat & z_dir);
	void redraw();
	inline void AddCamera(Camera * c) { this->cameras.push_back(c); } 
	inline void AddLight(LightSource* light) { this->m_lightSources.push_back(light); if(m_lightSources.size()==1) { activeLight=0;}} 
	inline void NextLight() { if(activeLight ==-1) return; activeLight = (activeLight + 1) % m_lightSources.size(); }
	inline void PreviousLight() { if(activeLight ==-1) return; activeLight = (activeLight + m_lightSources.size()-1) % m_lightSources.size(); }
	void SpinModel(const GLfloat & x_angle, const GLfloat & y_angle, const GLfloat & z_angle); //about self center.
	void RotateModelAboutX(const GLfloat & angle);//about worldX
	void RotateModelAboutY(const GLfloat & angle);//about worldY
	void RotateModelAboutZ(const GLfloat & angle);//about worldZ
	void RotateCamera(const GLfloat & x, const GLfloat & y, const GLfloat & z);
	void TranslateCamera(const GLfloat & x, const GLfloat & y, const GLfloat & z);
	inline void NextCamera() { activeCamera = (activeCamera + 1) % cameras.size(); }
	inline void PreviousCamera() { activeCamera = (activeCamera + cameras.size()-1) % cameras.size(); }
	inline void ToggleCameraDrawing() { this->m_drawCameras = (!this->m_drawCameras); }
	inline void ToggleLightsDrawing() { this->m_drawLights = (!this->m_drawLights); cout<<"now m_drawLights is "<<m_drawLights<<endl;}
	void ScaleActiveModel(const GLfloat & x, const GLfloat & y, const GLfloat & z);

	void SymScaleActiveModel(const GLfloat & r);

	void UpdateProjectionsForRatio( GLfloat ratio);

	void ToggleFaceNormals();
	void ToggleVertexNormals();
	void toggleBoundingBox();
	void FocusOnActiveModel();
	void addArk();
	void removeActiveModel();
	void removeAllModels();
	inline void SetRenderer( Renderer * r) { m_renderer = r; }
	inline void Zoom( GLfloat rate) { cameras[activeCamera]->Zoom(rate); }
	void MoveZNear(GLfloat len);
	void MoveZFar(GLfloat len);
	inline void SetActivePen(const Pen & p) {m_renderer->SetActivePen(p); }
	inline void SetPassivePen(const Pen & p) { m_renderer->SetPassivePen(p); }

	void TranslateCameraForward();
	void TranslateCameraBack();
	void TranslateCameraRight();
	void TranslateCameraLeft();
	void TranslateCameraUp();
	void TranslateCameraDown();
	void LeanCameraRight();
	void LeanCameraLeft();

	void RotateCameraUp();
	void RotateCameraDown();
	void RotateCameraRight();
	void RotateCameraLeft();

	void TranslateLight(const GLfloat & x, const GLfloat & y, const GLfloat & z);
	void RotateLightAboutX(const GLfloat & angle);
	void RotateLightAboutY(const GLfloat & angle);
	void RotateLightAboutZ(const GLfloat & angle);

	void addLightSource(LightSource * ls );

	vec3 SuggestMountingPoint() const;

};